package command

import (
	"errors"
	"fmt"
	"github.com/spf13/cobra"
	"greatTool/db"
	"greatTool/models"
	"greatTool/util"
	"os/exec"
	"runtime"
)

var AddCmd = &cobra.Command{
	Use:   "add [key] [value]",
	Short: "添加资源",
	Long:  `添加资源名字和对应的内容，如果资源名字有空格则加上 '' 或者 ""。`,
	Args:  cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		key := models.ValJsonKey{
			Key:  args[0],
			Type: models.ORIGIN,
		}

		// 检查key是否已存在
		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		if _, exists := resources[key]; exists {
			return errors.New("当前key已经存在数据: " + args[0])
		}

		// 创建新资源
		newResource := models.ValJson{
			Val: args[1],
			Tag: []string{},
		}

		if err := db.SaveResource(key, newResource); err != nil {
			return fmt.Errorf("保存资源失败: %w", err)
		}
		debug := cmd.Context().Value("debug").(bool)

		if err := db.RecordAudit(args[0], "add"); err != nil && debug {
			fmt.Printf("审计记录失败: %v\n", err)
		}

		fmt.Println("添加成功！")
		return nil
	},
}

var GetCmd = &cobra.Command{
	Use:   "get [key]",
	Short: "获取资源",
	Long:  `获取资源并进行标准输出，可以是资源的名字也可以是资源的标签。`,
	Args:  cobra.MaximumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		if len(args) == 0 {
			fmt.Println("【注意】：由于没有给出过滤条件，将列出全部的内容数据标题, 可以使用: ttl -h 或者 ttl --help 显示帮助。")
			fmt.Println()
			for key := range resources {
				if key.Type != models.TAG {
					fmt.Println("  ", key.Key)
				}
			}
			fmt.Println()
			return nil
		}
		debug := cmd.Context().Value("debug").(bool)

		return PossiblyRun(debug, "get", resources, args[0], func(key models.ValJsonKey, json models.ValJson) error {
			fmt.Println()
			if key.Type == models.ORIGIN {
				fmt.Println("资源：", key.Key)
			} else {
				fmt.Println("资源：", key.OriginKey)
			}
			fmt.Println()
			fmt.Println(json.Val)
			fmt.Println()
			fmt.Println("标签：", json.Tag)
			resourceKey := key.Key
			if key.Type == models.TAG {
				resourceKey = key.OriginKey
			}
			if err := db.RecordAudit(resourceKey, "get"); err != nil && debug {
				fmt.Printf("审计记录失败: %v\n", err)
			}
			// 添加历史记录
			if key.Type == models.TAG {
				resourceKey = key.OriginKey
			}
			return nil
		})
	},
}

var OpenCmd = &cobra.Command{
	Use:   "open [key]",
	Short: "打开资源",
	Long:  `如果可以打开资源则打开资源，否则将提示错误内容。`,
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}
		debug := cmd.Context().Value("debug").(bool)

		return PossiblyRun(debug, "open", resources, args[0], func(key models.ValJsonKey, json models.ValJson) error {
			switch os := runtime.GOOS; os {
			case "darwin":
				if debug {
					fmt.Println("当前系统是 macOS")
				}
				cmd := exec.Command("open", json.Val)
				return cmd.Run()
			case "linux":
				return errors.New("当前系统是 Linux - 未适配")
			case "windows":
				if debug {
					fmt.Println("当前系统是 Windows， 正在打开：", json.Val)
				}
				cmd := exec.Command("explorer", json.Val)
				return cmd.Run()
			default:
				return fmt.Errorf("当前系统是 %s - 未适配", os)
			}
		})
	},
}

var DelCmd = &cobra.Command{
	Use:     "del [key]",
	Aliases: []string{"rm"},
	Short:   "删除资源",
	Long:    `删除对应的资源（精准匹配）。`,
	Args:    cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		key := models.ValJsonKey{
			Key:  args[0],
			Type: models.ORIGIN,
		}

		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		_, exists := resources[key]
		if !exists {
			fmt.Printf("未找到该资源: %s\n", args[0])
			return nil
		}
		debug := cmd.Context().Value("debug").(bool)

		// 先清理历史记录
		db.CleanupResourceHistory(args[0], debug)

		if err := db.DeleteResource(key); err != nil {
			return fmt.Errorf("删除资源失败: %w", err)
		}

		fmt.Println("删除成功！")
		return nil
	},
}

var TagCmd = &cobra.Command{
	Use:   "tag [key] [tags...]",
	Short: "添加标签",
	Long:  `给指定的资源增加一个或多个标签，方便查看和操作。`,
	Args:  cobra.MinimumNArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		key := models.ValJsonKey{
			Key:  args[0],
			Type: models.ORIGIN,
		}

		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		resource, exists := resources[key]
		if !exists {
			return errors.New("未找到该资源")
		}

		// 添加新标签
		newTags := append(resource.Tag, args[1:]...)
		resource.Tag = util.RemoveDuplicates(newTags)

		if err := db.SaveResource(key, resource); err != nil {
			return fmt.Errorf("保存资源失败: %w", err)
		}

		fmt.Println("标签添加成功！")
		return nil
	},
}

var DtagCmd = &cobra.Command{
	Use:   "dtag [key] [tag]",
	Short: "删除标签",
	Long:  `删除资源的一个标签。`,
	Args:  cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		key := models.ValJsonKey{
			Key:  args[0],
			Type: models.ORIGIN,
		}

		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		resource, exists := resources[key]
		if !exists {
			return errors.New("未找到该资源")
		}

		// 删除指定标签
		newTags := make([]string, 0, len(resource.Tag))
		for _, tag := range resource.Tag {
			if tag != args[1] {
				newTags = append(newTags, tag)
			}
		}

		resource.Tag = newTags
		if err := db.SaveResource(key, resource); err != nil {
			return fmt.Errorf("保存资源失败: %w", err)
		}

		fmt.Println("标签删除成功！", args[1])
		return nil
	},
}

var RenameCmd = &cobra.Command{
	Use:     "rename [oldKey] [newKey]",
	Aliases: []string{"mv"},
	Short:   "重命名资源",
	Long:    `给资源改名字。`,
	Args:    cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		oldKey := models.ValJsonKey{
			Key:  args[0],
			Type: models.ORIGIN,
		}

		resources, err := db.GetAllResources()
		if err != nil {
			return fmt.Errorf("获取资源失败: %w", err)
		}

		resource, exists := resources[oldKey]
		if !exists {
			return errors.New("未找到该资源")
		}

		// 删除旧key
		if err := db.DeleteResource(oldKey); err != nil {
			return fmt.Errorf("删除旧资源失败: %w", err)
		}

		// 添加新key
		newKey := models.ValJsonKey{
			Key:  args[1],
			Type: models.ORIGIN,
		}

		if err := db.SaveResource(newKey, resource); err != nil {
			return fmt.Errorf("保存新资源失败: %w", err)
		}

		fmt.Println("重命名成功！")
		return nil
	},
}

var ConfigCmd = &cobra.Command{
	Use:   "config",
	Short: "显示配置信息",
	Long:  `显示数据文件的位置等信息。`,
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		configPath, err := db.GetDBPath()
		if err != nil {
			return fmt.Errorf("获取配置路径失败: %w", err)
		}
		fmt.Println("数据文件的位置：", configPath)
		return nil
	},
}

var VersionCmd = &cobra.Command{
	Use:   "version",
	Short: "显示版本信息",
	Long:  `显示当前工具的版本号。`,
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		fmt.Println(models.Version)
		return nil
	},
}

// UpdateCmd Update命令
var UpdateCmd = &cobra.Command{
	Use:     "update <key> <new_value>",
	Aliases: []string{"put", "mod"},
	Short:   "更新资源内容",
	Args:    cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {

		key := models.ValJsonKey{Key: args[0], Type: models.ORIGIN}
		debug := cmd.Context().Value("debug").(bool)
		if err := db.RecordAudit(args[0], "update"); err != nil && debug {
			fmt.Printf("审计记录失败: %v\n", err)
		}
		return db.UpdateResource(key, models.ValJson{Val: args[1]})
	},
}

// PossiblyRun 处理可能匹配多个资源的操作
func PossiblyRun(debug bool, opt string, resources map[models.ValJsonKey]models.ValJson, searchKey string,
	action func(models.ValJsonKey, models.ValJson) error) error {

	if debug {
		fmt.Println("当前是", opt, "操作")
	}

	// 查找匹配的资源
	matches := make(map[models.ValJsonKey]models.ValJson)
	for key, val := range resources {
		if util.ContainsIgnoreCase(key.Key, searchKey) {
			matches[key] = val
		}
	}

	if len(matches) == 0 {
		return errors.New("未找到当前资源，资源名: " + searchKey)
	}

	// 如果只有一个匹配项，直接执行
	if len(matches) == 1 {
		for key := range matches {
			return action(key, matches[key])
		}
	}

	// 多个匹配项，让用户选择
	fmt.Println("发现多个资源，请输入对应的序号获取对应的内容：")

	order := make([]models.ValJsonKey, 0, len(matches))
	idx := 1
	for key := range matches {
		fmt.Printf("%d. ", idx)
		if key.Type == models.ORIGIN {
			fmt.Println(key.Key)
		} else {
			fmt.Printf("%s (标签: %s)\n", key.OriginKey, key.Key)
		}
		order = append(order, key)
		idx++
	}

	var choice int
	if _, err := fmt.Scan(&choice); err != nil {
		return fmt.Errorf("输入无效: %w", err)
	}

	if choice < 1 || choice > len(order) {
		return errors.New("无效的选择")
	}

	selectedKey := order[choice-1]
	return action(selectedKey, matches[selectedKey])
}

var AuditCmd = &cobra.Command{
	Use:   "audit",
	Short: "查看审计统计",
	Long:  `查看资源的操作统计信息。`,
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		stats, err := db.GetAuditStats()
		if err != nil {
			return fmt.Errorf("获取审计统计失败: %w", err)
		}

		fmt.Println("=== 审计统计 ===")
		fmt.Printf("总操作次数: %d\n", stats.TotalOperations)
		fmt.Println()

		fmt.Println("按操作类型统计:")
		for op, count := range stats.ByOperation {
			fmt.Printf("  %s: %d\n", op, count)
		}
		fmt.Println()

		fmt.Println("按资源统计 (前10名):")
		// 按操作次数排序
		type resourceStat struct {
			key   string
			count int
		}
		var sortedStats []resourceStat
		for key, count := range stats.ByResource {
			sortedStats = append(sortedStats, resourceStat{key, count})
		}

		// 排序
		for i := 0; i < len(sortedStats)-1; i++ {
			for j := i + 1; j < len(sortedStats); j++ {
				if sortedStats[i].count < sortedStats[j].count {
					sortedStats[i], sortedStats[j] = sortedStats[j], sortedStats[i]
				}
			}
		}

		// 显示前10名
		for i, stat := range sortedStats {
			if i >= 10 {
				break
			}
			fmt.Printf("  %s: %d\n", stat.key, stat.count)
		}

		return nil
	},
}

var HistoryCmd = &cobra.Command{
	Use:   "history [limit]",
	Short: "查看操作历史",
	Long: `查看详细的操作历史记录，支持分页显示。
可选的 limit 参数指定显示最近多少条记录（默认20条）。`,
	Args: cobra.MaximumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		limit := 20
		if len(args) > 0 {
			if _, err := fmt.Sscanf(args[0], "%d", &limit); err != nil {
				return fmt.Errorf("无效的limit参数: %s", args[0])
			}
		}

		records, err := db.GetAllHistoryRecords()
		if err != nil {
			return fmt.Errorf("获取历史记录失败: %w", err)
		}

		if len(records) == 0 {
			fmt.Println("暂无历史记录")
			return nil
		}

		// 限制显示数量
		displayRecords := records
		if limit > 0 && len(records) > limit {
			displayRecords = records[:limit]
		}

		fmt.Println("=== 操作历史 ===")
		fmt.Printf("显示最近 %d 条记录 (共 %d 条)\n\n", len(displayRecords), len(records))

		for i, record := range displayRecords {
			displayText := record.ResourceKey
			if displayText == "" {
				displayText = record.Command
			}

			fmt.Printf("%4d. [%s] %-8s %s\n",
				i+1,
				record.TimeStr,
				record.Operation,
				displayText)
		}

		return nil
	},
}
